import 'dart:convert';
import 'dart:ui';

import 'package:carousel_slider/carousel_slider.dart';
import 'package:fluro/fluro.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:like_button/like_button.dart';
import 'package:mi_mang_flutter/api/daily_words_api.dart';
import 'package:mi_mang_flutter/api/favorite_words_api.dart';
import 'package:mi_mang_flutter/model/daily_word_model.dart';
import 'package:mi_mang_flutter/res/dimens.dart';
import 'package:mi_mang_flutter/res/styles.dart';
import 'package:mi_mang_flutter/routers/fluro_navigator.dart';
import 'package:mi_mang_flutter/utils/date_tools.dart';
import 'package:mi_mang_flutter/utils/image_utils.dart';
import 'package:mi_mang_flutter/utils/locale_util.dart';
import 'package:mi_mang_flutter/utils/shared_preferences.dart';
import 'package:mi_mang_flutter/utils/utils.dart';

import 'home_router.dart';

/// 每日一图
class DailyPicturePage extends StatefulWidget {
  DailyPicturePage({Key? key}) : super(key: key);

  @override
  _DailyPicturePageState createState() => _DailyPicturePageState();
}

class _DailyPicturePageState extends State<DailyPicturePage>
    with SingleTickerProviderStateMixin {
  // 每日一句数据组
  List<DailyWordModel?> list = [];
  // 当前选中的每日一句
  DailyWordModel? selectModel;
  // 当前选中的每日一句的索引
  int selectIndex = 0;

  List<List<List<Object?>>> listWeeks = [];
  int selectWeekIndex = 0;

  late Animation<double> animation;
  late AnimationController controller;

  final CarouselSliderController _carouselController = CarouselSliderController();
  final CarouselSliderController _weekCarouselController =
      CarouselSliderController();

  @override
  void initState() {
    super.initState();

    controller = AnimationController(
        duration: const Duration(milliseconds: 100), vsync: this);
    animation = Tween(
            begin: -(Dimens.statusBarHeight! +
                AppBar().preferredSize.height +
                Dimens.widthDp(150.0)),
            end: 0.0)
        .chain(CurveTween(curve: Curves.ease))
        .animate(controller)
      ..addListener(() {
        if (mounted) setState(() {});
      });

    var modelMap = SpUtil.getObject(SPKeys.HOME_DAILY_KEY);
    DailyWordModel? model;
    if (modelMap != null) {
      // 默认选中第一项,防止闪烁问题
      model = DailyWordModel.fromJson(modelMap);
      if (model.id != null) {
        selectModel = model;
        list.add(model);
        refreshWeekList();
      }
    }
    try {
      // 获取每日一句所有历史记录
      DailyWordsApi.getDailyWordsPage(
        pageNum: 1,
        pageSize: 9999999,
      ).then((val) {
        var listModel = val.data!.records!;
        if (model != null && model.id != null) {
          listModel.removeAt(0);
        }
        listModel.forEach((item) {
          list.insert(0, item);
        });
        selectIndex = list.length - 1;
        _carouselController.jumpToPage(selectIndex);
        refreshWeekList();
        _weekCarouselController.jumpToPage(selectWeekIndex);
        if (mounted) setState(() {});
      });
    } catch (e) {
    } finally {
      // 为了解决首次进入App时,未开启网络,导致没有数据时报异常的问题
      if (list.length == 0) {
        model = DailyWordModel();
        model.isFav = false;
        model.publishTime = DateTime.now();
        selectModel = model;
        list.add(model);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return AnnotatedRegion<SystemUiOverlayStyle>(
      value: SystemUiOverlayStyle.light,
      child: Scaffold(
        body: Stack(
          children: <Widget>[
            CarouselSlider.builder(
              options: CarouselOptions(
                height: double.infinity,
                viewportFraction: 1.0,
                enlargeCenterPage: false,
                enableInfiniteScroll: false,
                initialPage: selectIndex,
                scrollPhysics: ClampingScrollPhysics(),
                onPageChanged: (index, reason) {
                  selectIndex = index;
                  selectModel = list[index];
                  Utils.feedbackVibrate();
                  refreshWeekList();
                  _weekCarouselController.jumpToPage(selectWeekIndex);
                  if (mounted) setState(() {});
                },
              ),
              itemCount: list.length,
              itemBuilder: _swiperItem,
              carouselController: _carouselController,
            ),
            _buildHistory(),
            _buildAppbar(),
          ],
        ),
      ),
    );
  }

  Widget _swiperItem(BuildContext context, int index, int realIndex) {
    DailyWordModel model = list[index]!;
    return InkWell(
      child: loadNetworkAssetImage(
        model.imageUrl,
        key: Key("swiper_key_$index"),
        fit: BoxFit.cover,
        child: Column(
          children: <Widget>[
            Spacer(),
            _buildContent(model),
            Gaps.vBottomBarHeight,
          ],
        ),
      ),
      onTap: () {
        if (controller.isCompleted) {
          controller.reverse();
        }
      },
      onDoubleTap: () {
        if (!controller.isCompleted) {
          controller.forward();
        }
      },
    );
  }

  /// 底部导航按钮布局
  Widget _buildAppbar() {
    return Theme(
      data: ThemeData.dark(),
      child: SafeArea(
        bottom: false,
        child: Container(
          padding: EdgeInsets.symmetric(horizontal: Dimens.gapDp15),
          height: AppBar().preferredSize.height,
          width: double.infinity,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: <Widget>[
              Material(
                color: Colors.transparent,
                shape: CircleBorder(),
                clipBehavior: Clip.hardEdge,
                child: CloseButton(),
              ),
              Material(
                color: Colors.transparent,
                shape: CircleBorder(),
                clipBehavior: Clip.hardEdge,
                child: Stack(
                  alignment: Alignment.center,
                  children: <Widget>[
                    Text(
                      "${selectModel?.publishTime?.month ?? '1'}",
                      style: Theme.of(context)
                          .textTheme
                          .bodyMedium!
                          .copyWith(color: Colors.white, height: 1.9),
                    ),
                    IconButton(
                      tooltip: i18n(context).calendar,
                      splashColor: Colors.white24,
                      icon: Icon(Icons.calendar_today),
                      onPressed: () {
                        if (controller.isCompleted) {
                          controller.reverse();
                        } else {
                          controller.forward();
                        }
                      },
                    ),
                  ],
                ),
              ),
              Material(
                color: Colors.transparent,
                shape: CircleBorder(),
                clipBehavior: Clip.hardEdge,
                child: IconButton(
                  tooltip: i18n(context).share,
                  splashColor: Colors.white24,
                  icon: Icon(Icons.share),
                  onPressed: () {
                    var modelString =
                        Uri.encodeComponent(jsonEncode(selectModel));
                    NavigatorUtils.push(
                      context,
                      "${HomeRouter.dailyShare}?dialyModel=$modelString",
                      transition: TransitionType.fadeIn,
                    );
                  },
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  /// 弹出的每日一句历史记录的层
  Widget _buildHistory() {
    return Positioned(
      top: animation.value,
      left: 0.0,
      right: 0.0,
      child: ClipRect(
        // 背景过滤器
        child: BackdropFilter(
          filter: ImageFilter.blur(
            sigmaX: 10.0,
            sigmaY: 10.0,
          ),
          child: Container(
            height: Dimens.statusBarHeight! +
                AppBar().preferredSize.height +
                Dimens.widthDp(150.0),
            color: Colors.white38,
            alignment: Alignment.bottomCenter,
            child: CarouselSlider.builder(
              options: CarouselOptions(
                height: Dimens.widthDp(150.0),
                viewportFraction: 1.0,
                enlargeCenterPage: false,
                scrollPhysics: ClampingScrollPhysics(),
                initialPage: selectWeekIndex,
                onPageChanged: (index, reason) {
                  selectWeekIndex = index;
                  if (mounted) setState(() {});
                },
              ),
              itemCount: listWeeks.length,
              itemBuilder: (content, index, int realIndex) {
                var listDay = listWeeks[index];
                return Row(
                  children: listDay.map((item) {
                    return _historyItem(item);
                  }).toList(),
                );
              },
              carouselController: _weekCarouselController,
            ),
          ),
        ),
      ),
    );
  }

  // 根据周当前是第几周返回字符串
  Widget _weekItemWidget(DateTime date) {
    List<String> weekStrList = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
    String weekStr = weekStrList[date.weekday - 1];
    if (DateTools.isEqualDay(date, DateTime.now())) {
      weekStr = i18n(context).today;
    }
    return Text(weekStr);
  }

  // 每日一句周日历, 单元格布局
  Widget _historyItem(item) {
    var date = item[0] as DateTime;
    var model = item[1] as DailyWordModel?;
    return InkWell(
      child: Container(
        width: MediaQuery.of(context).size.width / 7,
        child: Column(
          children: <Widget>[
            _weekItemWidget(date),
            Gaps.vGap8,
            Stack(
              alignment: Alignment.center,
              children: <Widget>[
                if (model != null)
                  ClipOval(
                    child: loadNetworkImage(
                      model.imageUrl ?? '',
                      placeholder: "public/default_user",
                      width: 36.0,
                      height: 36.0,
                      fit: BoxFit.fill,
                    ),
                  ),
                if (model == null)
                  ClipOval(
                    child: Container(
                      color: Colors.black26,
                      width: 36.0,
                      height: 36.0,
                    ),
                  ),
                Text(
                  "${date.day}",
                  style: Theme.of(context)
                      .textTheme
                      .titleMedium!
                      .copyWith(color: Colors.white),
                ),
              ],
            ),
            Gaps.vGap5,
            if (DateTools.isEqualDay(selectModel!.publishTime!, date))
              Container(
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.red,
                ),
                width: Dimens.gapDp3,
                height: Dimens.gapDp3,
              )
          ],
        ),
      ),
      onTap: () {
        if (model != null) {
          selectModel = model;
          selectIndex = list.indexOf(model);
          Utils.feedbackVibrate();
          _carouselController.jumpToPage(selectIndex);
          if (mounted) setState(() {});
        }
      },
    );
  }

  /// 底部每日一句布局
  Widget _buildContent(DailyWordModel model) {
    return Padding(
      padding: EdgeInsets.symmetric(
        horizontal: Dimens.gapDp25,
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Text(
            model.content ?? "",
            style: Theme.of(context).textTheme.titleMedium!.copyWith(
                  height: 1.2,
                  color: Colors.white,
                ),
          ),
          Gaps.vGap8,
          Text(
            "—— ${model.source ?? ''}",
            style: Theme.of(context)
                .textTheme
                .titleMedium!
                .copyWith(color: Colors.white),
          ),
          _buildButton(model),
          Gaps.vGap5,
        ],
      ),
    );
  }

  /// 点赞按钮布局
  Widget _buildButton(DailyWordModel model) {
    return Container(
      height: Dimens.gapDp35,
      child: LikeButton(
        mainAxisAlignment: MainAxisAlignment.end,
        likeBuilder: (bool isLiked) {
          return Icon(
            isLiked ? Icons.favorite : Icons.favorite_border,
            color: isLiked ? const Color(0xFFF44336) : Colors.white,
            size: Dimens.gapDp25,
          );
        },
        countPostion: CountPostion.left,
        likeCount: model.favCount ?? 0,
        likeCountPadding: const EdgeInsets.only(right: 8.0),
        countBuilder: (int? count, bool isLiked, String text) {
          return Text(
            text,
            style: TextStyle(
              fontSize: 16.0,
              color: Colors.white,
            ),
          );
        },
        isLiked: model.isFav ?? false,
        onTap: (isLiked) {
          Utils.feedbackVibrate();
          if (isLiked) {
            return _favoriteWordsRemove();
          } else {
            return _favoriteWordsSave();
          }
        },
      ),
    );
  }

  /// 点赞
  /// 返回true则更改为取消收藏状态
  Future<bool> _favoriteWordsSave() async {
    var response =
        await FavoriteWordsApi.favoriteWordsSave(selectModel?.id ?? '' as int);
    // 判断请求是否成功, 请求成功则更新点赞状态为true
    selectModel!.isFav = response.data == true;
    return Future.value(selectModel!.isFav);
  }

  /// 取消点赞
  /// 返回false则更改为取消收藏状态
  Future<bool> _favoriteWordsRemove() async {
    var response = await FavoriteWordsApi.favoriteWordsRemove(
        selectModel?.id ?? '' as int);
    // 判断请求是否成功, 请求成功则更新点赞状态为false
    selectModel!.isFav = !(response.data == true);
    return Future.value(selectModel!.isFav);
  }

  void refreshWeekList() {
    var firstModel = list.first!;
    var lastModel = list.last!;
    // 获取两个日期之间,周的第一天与周的最后一天,用于控制总共有多少有组
    var firstDayOfWeek = DateTools.firstDayOfWeek(firstModel.publishTime!);
    var lastDayOfWeek = DateTools.lastDayOfWeek(lastModel.publishTime!);
    // 两个日期相隔多少天,决定总共有多少个元素
    final difference = lastDayOfWeek.difference(firstDayOfWeek).inDays;
    // 根据相差天数创建每一天的日期
    var listDate = List.generate(
        difference, (int index) => firstDayOfWeek.add(Duration(days: index)));
    // 创建周的数组,每周包含七天日期
    // 最底下的数据是日期对应的每日一句, 格式如: [日期, 每日一句]; 每日一句为空时,表示当天没有数据
    listWeeks = List.generate((listDate.length / 7).floor(), (i) {
      return List.generate(7, (j) {
        // 把每日一句的数据放置到对应的日期下, 用数组对应起来
        var date = listDate[(i * 7) + j];
        var model = list.firstWhere((item) {
          return DateTools.isEqualDay(item!.publishTime!, date);
        }, orElse: () {
          // 未查到数据时返回 null
          return null;
        });
        return [date, model];
      });
    });

    // 当前选中的天索引
    int weekIndex = listDate.indexWhere((date) {
      return DateTools.isEqualDay(date.toLocal(), selectModel!.publishTime!);
    });
    // 每日一图周日历选中索引
    selectWeekIndex = ((weekIndex + 1) / 7).ceil() - 1;
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}
